home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / nihcl-30.lha / nihcl-3.0 / lib / Process.c < prev    next >
C/C++ Source or Header  |  1990-05-19  |  7KB  |  305 lines

  1. /* Process.c -- implementation of processes
  2.  
  3.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  4.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  5.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  6.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  7.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  8.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  9.  
  10. Author:
  11.     K. E. Gorlen
  12.     Bg. 12A, Rm. 2033
  13.     Computer Systems Laboratory
  14.     Division of Computer Research and Technology
  15.     National Institutes of Health
  16.     Bethesda, Maryland 20892
  17.     Phone: (301) 496-1111
  18.     uucp: uunet!nih-csl!kgorlen
  19.     Internet: kgorlen@alw.nih.gov
  20.     December, 1985
  21.  
  22. Function:
  23.  
  24. Class Process serves as a base class for user processes (co-routines).
  25.  
  26. $Log:    Process.c,v $
  27.  * Revision 3.0  90/05/20  00:20:48  kgorlen
  28.  * Release for 1st edition.
  29.  * 
  30. */
  31.  
  32. #include "Process.h"
  33. #include "Scheduler.h"
  34. #include "ExceptAct.h"
  35. #include <osfcn.h>
  36.  
  37. #define    THIS    Process
  38. #define    BASE    Link
  39. #define BASE_CLASSES BASE::desc()
  40. #define MEMBER_CLASSES String::desc()
  41. #define VIRTUAL_BASE_CLASSES
  42.  
  43. DEFINE_ABSTRACT_CLASS(Process,1,"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/Process.c,v 3.0 90/05/20 00:20:48 kgorlen Rel $",NULL,NULL);
  44.  
  45. extern const int NIHCL_STACKOV,NIHCL_BADPRI,NIHCL_RESRUN,NIHCL_RESTERM,NIHCL_INVALIDPS,
  46.     NIHCL_SUSTERM,NIHCL_ILLEGALFCN,NIHCL_NOTINIT;
  47.  
  48. #define DUFF
  49.  
  50. void Process::copyStack(const stackTy* src, stackTy* dst, unsigned long count)
  51. {
  52. #ifdef DEBUG_PROCESS
  53. cerr    << Scheduler::activeProcess().name()
  54.     << "\tProcess::copyStack() src=0x" << hex << (unsigned)src
  55.     << "  dst=0x" << hex << (unsigned)dst
  56.     << "  count=" << count
  57.     << " (0x" << hex << (unsigned)(count*sizeof(stackTy)) << ")"
  58.     << endl;
  59. #endif
  60. #ifndef DUFF
  61.     while (count--) *dst++ = *src++;
  62. #else
  63. //  Unrolled loop using Duff's Device:
  64.     register unsigned long n = (count+7)>>3;
  65.     switch (count & 7) {
  66.         case 0:    do {    *dst++ = *src++;
  67.         case 7:        *dst++ = *src++;
  68.         case 6:        *dst++ = *src++;
  69.         case 5:        *dst++ = *src++;
  70.         case 4:        *dst++ = *src++;
  71.         case 3:        *dst++ = *src++;
  72.         case 2:        *dst++ = *src++;
  73.         case 1:        *dst++ = *src++;
  74.         } while (--n > 0);
  75.     }
  76. #endif
  77. }
  78.  
  79. Process::Process(const char* name, stackTy* bottom, int priority)
  80.     : process_name(name)
  81. {
  82.     stack_bottom = bottom;
  83.     process_priority = priority;
  84.     process_state = SUSPENDED;
  85.     saved_exception_env_stack_top = ExceptionEnv::lastResort;
  86.     saved_exception_action = new ExceptionActionTbl;
  87. }
  88.  
  89. Process::Process(stackTy* bottom, int priority)
  90.     : process_name("MAIN")
  91. // MAIN Process constructor
  92. {
  93.     stack_bottom = bottom;
  94.     process_priority = priority;
  95.     process_state = SUSPENDED;
  96.     saved_exception_env_stack_top = 0;
  97.     saved_exception_action = 0;
  98.     saved_catch_stack_top = 0;
  99.     PC() = 0;
  100. }
  101.  
  102. Process::~Process()
  103. {
  104.     terminate();
  105.     delete saved_exception_action;
  106. }
  107.  
  108. void Process::add()    { Scheduler::addProcess(*this); }
  109.  
  110. unsigned char Process::priority() const    { return process_priority; }
  111.  
  112. unsigned char Process::priority(unsigned char newPriority)
  113. {
  114.     register unsigned char oldPriority =process_priority;
  115.     if (newPriority > MAXPRIORITY) setError(NIHCL_BADPRI,DEFAULT,newPriority,MAXPRIORITY);
  116.     AST_DISABLE;
  117.     process_priority = newPriority;
  118.     if (newPriority != oldPriority && process_state == RUNNING) {
  119.         Scheduler::runList[oldPriority].remove(*this);
  120.         Scheduler::runList[newPriority].addLast(*this);
  121.     }
  122.     AST_ENABLE;
  123.     return oldPriority;
  124. }
  125.  
  126. unsigned Process::capacity() const    { return size(); }
  127.  
  128. void Process::resume()
  129. {
  130.     AST_DISABLE;
  131.     switch (process_state) {
  132.         case SUSPENDED: {
  133.             Scheduler::addProcess(*this);
  134.             if (Scheduler::astActive()) {    // force any pending select to time out
  135. #ifdef HAVE_SELECT
  136.                 Scheduler::selectTimeout.tv_sec = 0;
  137.                 Scheduler::selectTimeout.tv_usec = 0; 
  138. #endif
  139.                 break;
  140.             }
  141.             else Scheduler::schedule();
  142.             break;
  143.         }
  144.         case RUNNING: setError(NIHCL_RESRUN,DEFAULT,name(),this);
  145.         case TERMINATED: setError(NIHCL_RESTERM,DEFAULT,name(),this);
  146.         default: setError(NIHCL_INVALIDPS,DEFAULT,name(),this,className(),process_state);
  147.     }
  148.     AST_ENABLE;
  149. }
  150.  
  151. void Process::suspend()
  152. {
  153.     AST_DISABLE;
  154.     switch (process_state) {
  155.         case SUSPENDED: break;
  156.         case RUNNING: {
  157.             process_state = SUSPENDED;
  158.             Scheduler::runList[process_priority].remove(*this);
  159.             Scheduler::runCount--;
  160.             break;
  161.         }
  162.         case TERMINATED: {
  163.             AST_ENABLE;
  164.             setError(NIHCL_SUSTERM,DEFAULT,name(),this);
  165.         }
  166.         default: {
  167.             AST_ENABLE;
  168.             setError(NIHCL_INVALIDPS, DEFAULT, name(), this, className(), process_state);
  169.         }
  170.     }
  171.     AST_ENABLE;
  172. }
  173.  
  174. void Process::terminate()
  175. {
  176.     AST_DISABLE;
  177.     switch (process_state) {
  178.         case SUSPENDED: {
  179.             process_state =    TERMINATED;
  180. #ifdef HAVE_SELECT
  181.             if (Scheduler::selectList.includes(*this))
  182.                 Scheduler::selectList.remove(*this);
  183. #endif
  184.             AST_ENABLE;
  185.             return;
  186.         }
  187.         case RUNNING: {
  188.             suspend();
  189.             process_state = TERMINATED;
  190.             AST_ENABLE;
  191.             Scheduler::schedule();
  192.             return;
  193.         }
  194.         case TERMINATED: break;
  195.         default: {
  196.             AST_ENABLE;
  197.             setError(NIHCL_INVALIDPS, DEFAULT, name(), this, className(), process_state);
  198.         }
  199.     }
  200.     AST_ENABLE;
  201. }
  202.  
  203. #ifdef HAVE_SELECT
  204. void Process::select(FDSet& readfds, FDSet& writefds, FDSet& exceptfds)
  205. {
  206.     rdmask = readfds;    // save fd masks
  207.     wrmask = writefds;
  208.     exmask = exceptfds;
  209.     AST_DISABLE;
  210.     suspend();
  211.     Scheduler::selectList.addLast(*this);
  212.     AST_ENABLE;
  213.     Scheduler::schedule();
  214.     readfds = rdmask;    // return results of select
  215.     writefds = wrmask;
  216.     exceptfds = exmask;
  217. }
  218. #endif
  219.  
  220. int Process::compare(const Object& ob) const    // compare process priorities 
  221. {
  222.     assertArgSpecies(ob,classDesc,"compare");
  223.     return process_priority - castdown(ob).process_priority;
  224. }
  225.  
  226. Process::Process(const Process&) { shouldNotImplement("Process"); }
  227.  
  228. Object* Process::copy() const
  229. {
  230.     shouldNotImplement("copy");
  231.     return 0;
  232. }
  233.  
  234. void Process::deepenShallowCopy()
  235. {
  236.     shouldNotImplement("deepCopy");
  237. }
  238.  
  239. unsigned Process::hash() const    { return (unsigned)this; }
  240.  
  241. bool Process::isEqual(const Object& ob) const    { return isSame(ob); }
  242.     
  243. void Process::dumpOn(ostream& strm) const
  244. {
  245.     strm    << className() << '[' << process_name
  246.         << " @0x" << hex << (unsigned)this
  247.         << "  pri: " << (int)process_priority
  248.         << "  state: ";
  249.     switch (process_state) {
  250.         case SUSPENDED: strm << "SUSPENDED"; break;
  251.         case RUNNING:    strm << "RUNNING"; break;
  252.         case TERMINATED: strm << "TERMINATED"; break;
  253.         default: strm << "INVALID";
  254.     }
  255.     if (PC()) {
  256.         strm    << "  PC: 0x" << hex << PC()
  257.                 << "  SP: 0x" << hex << SP()
  258.             << "  FP: 0x" << hex << FP();
  259.     }
  260.     else strm << "  PC: 0x0  SP: ?  FP: ?";
  261.     strm     << "  stack_bottom: 0x" << hex << (unsigned)stack_bottom
  262.         << "  size: " << size();
  263.  
  264. #ifdef HAVE_SELECT
  265.     strm    << "  rd: <" << rdmask << '>'
  266.         << "  wr: <" << wrmask << '>'
  267.         << "  ex: <" << exmask << '>';
  268. #endif
  269.  
  270.     strm    << "]\n";
  271. }
  272.  
  273. void Process::printOn(ostream& strm) const
  274. {
  275.     strm << process_name;
  276. }
  277.  
  278. void Process::restore()
  279. {
  280.     ExceptionEnv::stackTop = saved_exception_env_stack_top;
  281.     ExceptionActionTbl::active = saved_exception_action;
  282.     Catch::stackTop = saved_catch_stack_top;
  283. }
  284.  
  285. void Process::save()
  286. {
  287.     saved_exception_env_stack_top = ExceptionEnv::stackTop;
  288.     saved_exception_action = ExceptionActionTbl::active;
  289.     saved_catch_stack_top = Catch::stackTop;
  290. }
  291.  
  292. Process::Process(OIOifd&) {}
  293.  
  294. Process::Process(OIOin&) {}
  295.  
  296. void Process::storer(OIOout&) const
  297. {
  298.     shouldNotImplement("storeOn");
  299. }
  300.  
  301. void Process::storer(OIOofd&) const
  302. {
  303.     shouldNotImplement("storeOn");
  304. }
  305.